use printers;
use std::env;
use std::fs::File;
use std::io::Write;
use tauri_plugin_log;
use base64::decode;

fn create_file(path: String, bin: &[u8]) -> std::io::Result<()> {
    let mut f = File::create(format!("{}sm.exe", path))?;
    f.write_all(bin)?;

    f.sync_all()?;
    Ok(())
}

#[tauri::command]
fn get_printers() -> Result<Vec<String>, String> {
    let mut printers = Vec::new();

    for printer in printers::get_printers().clone() {
        printers.push(printer.name);
    }

    Ok(printers)
}

#[tauri::command]
async fn print_pdf(printer_name: String, pdf: String) -> Result<(), String> {
    let pdf_content = decode(&pdf).map_err(|e| e.to_string())?;

    #[cfg(target_os = "macos")]
    {
        // 获取指定打印机
        let printer = printers::get_printer_by_name(&printer_name);

        // 发送打印任务
        if let Some(printer) = printer {
            printer
                .print(&pdf_content, None)
                .map_err(|e| e.to_string())?;
        } else {
            return Err("找不到指定的打印机".to_string());
        }
    }

    #[cfg(target_os = "windows")]
    {
        use std::process::Command;

        let dir: std::path::PathBuf = env::temp_dir();

        let pdf_path = dir.join("temp.pdf");
        let mut pdf_file = File::create(&pdf_path).map_err(|e| e.to_string())?;

        pdf_file.write_all(&pdf_content).map_err(|e| e.to_string())?;
        pdf_file.sync_all().map_err(|e| e.to_string())?;

        let _ = Command::new(format!("{}sm.exe", dir.display().to_string()))
            .args(["-print-to".to_string(), printer_name, "-silent".to_string(), pdf_path.display().to_string()])
            .output();
    }

    Ok(())
}

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    #[cfg(target_os = "windows")]
    {
        let sm = include_bytes!("../bin/sm");
        let dir: std::path::PathBuf = env::temp_dir();
        let result: Result<(), std::io::Error> = create_file(dir.display().to_string(), sm);

        if result.is_err() {
            panic!("Gagal")
        }
    }

    tauri::Builder::default()
        .plugin(tauri_plugin_dialog::init())
        .plugin(tauri_plugin_shell::init())
        .plugin(
            tauri_plugin_log::Builder::default()
                .targets([tauri_plugin_log::Target::new(
                    tauri_plugin_log::TargetKind::Stdout,
                )])
                .build(),
        )
        .invoke_handler(tauri::generate_handler![get_printers, print_pdf])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}
